// Client.cpp: implementation of the Client class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "kwclientcore.h"
#include "Client.h"
#include "CoalMineUnit.h"
#include "ClientConfiguration.h"
#include "AlarmDataManager.h"

#include "CommonLib\Structure.h"
#include "CommonLib\Packet.h"
#include "CommonLib\TimeUtility.h"

#include "CommClientLib\CommWithServer.h"

#include "MonitoringUnitLib\BaseMonitoringUnit.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Client::Client()
{

}

Client::~Client()
{

}

Client * Client::m_pInstance = NULL;

Client * Client::Instance()
{
  if (m_pInstance == NULL)
  {
    m_pInstance = new Client;
  }

  return m_pInstance;
}

void Client::DeleteInstance()
{
  if (m_pInstance) delete m_pInstance;

  m_pInstance = NULL;
}

void Client::Init()
{
	CWaitCursor waitcursor;
	
	VizClientServer * pVcs = new VizClientServer;
	pVcs->m_dwMethodType = VCS_MT_QUERYCOALMINEINFO;
	
	Packet packetRequest(sizeof(VizClientServer), (LPBYTE)pVcs);
	
	delete pVcs;
	
	Packet packetAck;
	packetAck.m_dwId = CommWithServer::Instance()->SendRequest(packetRequest);
	
	//2005-6-22
	int icount=0;
	while(1){
		icount++;
		if(icount>11)break;
		CommWithServer::Instance()->Receive(packetAck);
		
		CoalMineInfoStruct * pCoalMineInfoStruct = (CoalMineInfoStruct *)packetAck.GetpData();
		if(!pCoalMineInfoStruct || pCoalMineInfoStruct->m_nMethodAck != VCS_MR_OK)continue;
		if (pCoalMineInfoStruct->m_nMethodAck == VCS_MR_OK)
		{
			Client * pClient = Client::Instance();
			for (int i = 0;i < pCoalMineInfoStruct->m_dwNumOfItems;i++)
			{
				CoalMineInfoItem * pCoalMineInfoItem = &pCoalMineInfoStruct->m_CoalMineInfoItems[i];
				
				BaseCoalMineUnit * pCoalMineUnit = new CoalMineUnit(pClient);
				pClient->AddCoalMineUnit(pCoalMineUnit, pCoalMineInfoItem->m_nId, pCoalMineInfoItem->m_szName, pCoalMineInfoItem->m_szIPAddr);
				pCoalMineUnit->SetbConnected(pCoalMineInfoItem->m_bConnected);
				
				{
					DefinitionQueryStructEx * pDefinitionQueryStruct = new DefinitionQueryStructEx;
					pDefinitionQueryStruct->m_dwMethodType = VCS_MT_QUERYDEFINITION_EX;
					pDefinitionQueryStruct->m_dwBufSize = sizeof(DefinitionQueryStructEx);
					pDefinitionQueryStruct->m_nCoalMineId = pCoalMineUnit->GetId();
					pDefinitionQueryStruct->m_dwNumOfItems = 0;
					
					Packet packetReq(sizeof(DefinitionQueryStruct), (LPBYTE)pDefinitionQueryStruct);
					
					delete pDefinitionQueryStruct;
					
					Packet packetAck;
					packetAck.m_dwId = CommWithServer::Instance()->SendRequest(packetReq);
					CommWithServer::Instance()->Receive(packetAck);
					
					DefinitionAckStructEx * pDefinitionAckStruct = (DefinitionAckStructEx *)packetAck.GetpData();
					
					if (pDefinitionAckStruct && pDefinitionAckStruct->m_nMethodAck == VCS_MR_OK)
					{
						for (int j = 0;j < pDefinitionAckStruct->m_dwNumOfItems;j++)
						{
							MonUnitDefEx * pMonUnitDef = &pDefinitionAckStruct->m_DefItems[j].m_MonUnitDef;
							BaseMonitoringUnit * pMonitoringUnit = pCoalMineUnit->NewMonitoringUnitByModality((MonitoringUnitModality::Modalities)pMonUnitDef->m_nModality);
							pMonitoringUnit->ConvertDefFromStruct(pMonUnitDef);
							CTime time = ClientConfiguration::Instance()->GetServerTime();
							pMonitoringUnit->SetDataTime(time);
							pMonitoringUnit->SetStateChangeTime(time);
							pCoalMineUnit->AddMonitoringUnit(pMonitoringUnit);
						}
						pCoalMineUnit->SortMonUnits(ClientConfiguration::Instance()->m_Options.m_nSortBy);
					}
				}
				
				{
					DataQueryStructEx * pDataQueryStruct = new DataQueryStructEx;
					pDataQueryStruct->m_dwMethodType = VCS_MT_QUERYDATA_EX;
					pDataQueryStruct->m_dwBufSize = sizeof(DataQueryStructEx);
					pDataQueryStruct->m_nCoalMineId = pCoalMineUnit->GetId();
					pDataQueryStruct->m_dwNumOfItems = 0;
					
					Packet packetReq(sizeof(DataQueryStruct), (LPBYTE)pDataQueryStruct);
					
					delete pDataQueryStruct;
					
					Packet packetAck;
					packetAck.m_dwId = CommWithServer::Instance()->SendRequest(packetReq);
					CommWithServer::Instance()->Receive(packetAck);
					
					DataAckStruct * pDataAckStruct = (DataAckStruct *)packetAck.GetpData();
					
					if (pDataAckStruct && pDataAckStruct->m_nMethodAck == VCS_MR_OK)
					{
						for (int j = 0;j < pDataAckStruct->m_dwNumOfItems;j++)
						{
							MonUnitData * pMonUnitData = &pDataAckStruct->m_DataItems[j].m_MonUnitData;
							BaseMonitoringUnit * pMonitoringUnit = pCoalMineUnit->GetMonitoringUnitById(pMonUnitData->m_szId);
							if (pMonitoringUnit)
							{
								pCoalMineUnit->SetData(pMonitoringUnit, CTime(pMonUnitData->m_stData), (MonitoringUnitState::States)pMonUnitData->m_nState, pMonUnitData->m_fValue, false);
								AlarmDataManager::Instance()->UpdateAlarmData(pCoalMineUnit, pMonitoringUnit, NULL);
							}
						}
					}
				}
			}
			break;
		}
	}
}

void Client::Cleanup()
{
  DeleteAllRealtimeRecordManager();
}

RealtimeRecordManager * Client::NewRealtimeRecordManager(long nCoalMineId, const CString& strMonUnitId)
{
  RealtimeRecordManager * pRealtimeRecordMgr = new RealtimeRecordManager(nCoalMineId, strMonUnitId);
  AddRealtimeRecordManager(pRealtimeRecordMgr);
  AppendRealtimeRecord(pRealtimeRecordMgr, nCoalMineId, strMonUnitId);
  return pRealtimeRecordMgr;
}

void Client::AddRealtimeRecordManager(RealtimeRecordManager * pRealtimeRecordMgr)
{
  m_RTRecordMgrs.push_back(pRealtimeRecordMgr);
}

void Client::DeleteAllRealtimeRecordManager()
{
  for (int i = 0;i < m_RTRecordMgrs.size();i++)
  {
    RealtimeRecordManager * pRealtimeRecordMgr = m_RTRecordMgrs[i];
    delete pRealtimeRecordMgr;
  }
  m_RTRecordMgrs.clear();
}

RealtimeRecordManager * Client::GetRealtimeRecordManagerById(long nCoalMineId, const CString& strMonUnitId)
{
  for (int i = 0;i < m_RTRecordMgrs.size();i++)
  {
    RealtimeRecordManager * pRealtimeRecordMgr = m_RTRecordMgrs[i];
    if (pRealtimeRecordMgr->GetCoalMineId() == nCoalMineId && pRealtimeRecordMgr->GetMonUnitId() == strMonUnitId)
    {
      return pRealtimeRecordMgr;
    }
  }
  return NULL;
}

void Client::AppendRealtimeRecord(RealtimeRecordManager * pRealtimeRecordMgr, long nCoalMineId, const CString& strMonUnitId)
{
  BaseCoalMineUnit * pCoalMineUnit = GetCoalMineUnitById(nCoalMineId);
  if (!pCoalMineUnit) return;
  BaseMonitoringUnit * pMonitoringUnit = pCoalMineUnit->GetMonitoringUnitById(strMonUnitId);
  if (!pMonitoringUnit) return;

  RealtimeRecord record;
  pMonitoringUnit->MakeRealtimeRecord(&record);
  pRealtimeRecordMgr->AppendRecord(record);
  CTime time = ClientConfiguration::Instance()->GetServerTime();
  TimeUtility::DecDay(time);
  pRealtimeRecordMgr->DiscardRecordsEarlierThan(time);
}

void Client::AppendRealtimeRecord(RealtimeRecordManager * pRealtimeRecordMgr, BaseMonitoringUnit * pMonitoringUnit)
{
  if (!pMonitoringUnit) return;

  RealtimeRecord record;
  pMonitoringUnit->MakeRealtimeRecord(&record);
  pRealtimeRecordMgr->AppendRecord(record);
  CTime time = ClientConfiguration::Instance()->GetServerTime();
  TimeUtility::DecDay(time);
  pRealtimeRecordMgr->DiscardRecordsEarlierThan(time);
}
